package com.anxin.act.model.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.anxin.act.config.entity.WfApplyForm;
import com.anxin.act.config.service.WfApplyFormFieldService;
import com.anxin.act.config.service.WfApplyFormService;
import com.anxin.act.model.dao.WfActApproverDao;
import com.anxin.act.model.dto.ActModelExportDTO;
import com.anxin.act.model.entity.WfActApprover;
import com.anxin.act.model.vo.ActModelVo;
import com.anxin.common.constant.HttpStatus;
import com.anxin.common.utils.LogUtils;
import com.anxin.common.utils.StringUtils;
import com.anxin.common.utils.file.AttUtils;
import com.anxin.common.utils.file.FileUtils;
import com.anxin.common.utils.sys.UserUtils;
import com.anxin.framework.config.RuoYiConfig;
import com.anxin.framework.web.entity.AjaxResult;
import com.anxin.framework.web.page.PageDomain;
import com.anxin.framework.web.page.TableDataInfo;
import com.anxin.framework.web.page.TableSupport;
import com.anxin.sys.file.utils.FileBaseMoreDownLoad;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.util.IoUtil;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * 工作流模型Service
 *
 * @author: liuxiangyu
 * @date: 2020/3/5 13:40
 */
@Service
public class ActModelService {
    private static Logger logger = LoggerFactory.getLogger("sys-error");

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private WfActApproverService wfActApproverService;

    @Autowired
    private WfActApproverDao wfActApproverDao;

    @Autowired
    private WfApplyFormService wfApplyFormService;

    // BPMN 文件后缀
    private static String BPMN = ".bpmn20.xml";
    // 流程分类后缀
    private static String CATEGORY = ".category.txt";
    // 流程表单后缀
    private static String FORM = ".form.txt";
    // 申请人后缀
    private static String APPROVAL = ".wf_act_approval.txt";




    /**
     * 根据模型ID获取模型
     *
     * @param id
     * @return
     */
    public ActModelVo get(String id) {
        Model model = repositoryService.getModel(id);
        return new ActModelVo(model);
    }

    /**
     * 查询模型列表
     *
     * @param actModelVo
     * @return
     */
    public TableDataInfo findList(ActModelVo actModelVo) {
        PageDomain pageDomain = TableSupport.buildPageRequest();

        ModelQuery modelQuery = repositoryService.createModelQuery().latestVersion().orderByLastUpdateTime().desc();

        if (StringUtils.isNotBlank(actModelVo.getName())) {
            modelQuery.modelNameLike("%" + actModelVo.getName() + "%");
        }

        if (StringUtils.isNotBlank(actModelVo.getKey())) {
            modelQuery.modelKey(actModelVo.getKey());
        }

        if (StringUtils.isNotBlank(actModelVo.getCategory())) {
            modelQuery.modelCategory(actModelVo.getCategory());
        }

        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setRows(modelQuery.listPage(pageDomain.getFirstResult(), pageDomain.getMaxResults()));
        rspData.setTotal(modelQuery.count());
        return rspData;
    }

    /**
     * 复制模型
     * @param actModelVo
     * @return
     */
    public AjaxResult copyModel(ActModelVo actModelVo){

        // 获取复制源流程的模型信息
        byte[] bytes = repositoryService.getModelEditorSource(actModelVo.getId());
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            // 获取流程设计节点信息
            ObjectNode sourceObjectNode = (ObjectNode) new ObjectMapper().readTree(bytes);
            // 创建复制的目标流程模型, 填充部分默认信息
            Model newModel = repositoryService.newModel();
            ObjectNode modelNode = objectMapper.createObjectNode();
            newModel.setKey(actModelVo.getKey());
            // 填充模型名称, 其中在activiti7.1.M6版本中该name值必须定义为SpringAutoDeployment
            newModel.setName(actModelVo.getName());
            newModel.setVersion(1);
            newModel.setCategory(actModelVo.getCategory());
            // 其余的信息填充可选填
            modelNode.put(ModelDataJsonConstants.MODEL_NAME, actModelVo.getName());
            modelNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
            modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, "1");
            modelNode.put("formType", actModelVo.getFormType());
            modelNode.put("formId", actModelVo.getFormId());
            newModel.setMetaInfo(modelNode.toString());
            // 保存模型
            repositoryService.saveModel(newModel);
            // 对源流程信息进行深拷贝
            ObjectNode editorNode = sourceObjectNode.deepCopy();

            // 复制流程审批人和抄送人
            this.copyApprover(newModel,editorNode);

            // 以下信息可以通过debugger查看源流程信息, 定义新的流程信息后进行覆盖
            ObjectNode properties = objectMapper.createObjectNode();
            // 流程key的唯一性, 复制后的流程key需要更新, 可定义为源key_copy
            properties.put("process_id", actModelVo.getKey());
            properties.put("name", actModelVo.getName());
            properties.put("author", UserUtils.getUser().getId());
            // 根据源流程复制后的属性信息覆盖
            editorNode.set("properties", properties);
            // 保存新的流程模型的设计信息
            repositoryService.addModelEditorSource(newModel.getId(), editorNode.toString().getBytes(StandardCharsets.UTF_8));
            // 复制成功, 根据新的流程模型设计流程信息发布, 启动实例验证即可
        } catch (IOException e) {
            LogUtils.error("流程复制错误",e);
        }


        return AjaxResult.success();
    }

    /**
     * 复制审批人
     * @param newModel
     * @param editorNode
     */
    public void copyApprover(Model newModel,ObjectNode editorNode){
        JsonNode childShapes = editorNode.get("childShapes");
        Iterator<JsonNode> elements = childShapes.elements();
        while (elements.hasNext()){
            JsonNode node = elements.next();
            if (node.get("stencil") != null && node.get("stencil").get("id") != null && "UserTask".equals(node.get("stencil").get("id").asText()) ){

                String text = null;
                JsonNode jsonNode = null;
                String fieldName = null;
                // 复制审批人
                if (node.get("properties") != null
                        && node.get("properties").get("usertaskassignment") != null
                        && node.get("properties").get("usertaskassignment").get("assignment") != null
                        && node.get("properties").get("usertaskassignment").get("assignment").get("candidateUsers") != null
                        && node.get("properties").get("usertaskassignment").get("assignment").get("candidateUsers").size() > 0) {

                    text = node.get("properties").get("usertaskassignment").get("assignment").get("candidateUsers").get(0).get("value").asText();
                    jsonNode = node.get("properties").get("usertaskassignment").get("assignment").get("candidateUsers").get(0);
                    fieldName = "value";
                }else if (node.get("properties") != null && node.get("properties").get("multiinstance_collection") != null){
                    text = node.get("properties").get("multiinstance_collection").asText();
                    jsonNode = node.get("properties");
                    fieldName = "multiinstance_collection";
                }


                if (StringUtils.isNotBlank(text)){
                    if (text.startsWith("${approverListener.getApproverString") || text.startsWith("${approverListener.getApproverList") ){
                        String[] splits = text.split("'");
                        String actUuid = splits[1];
                        String modelId = splits[3];

                        text = text.replaceAll(actUuid,wfActApproverService.copyByUuid(actUuid));
                        text = text.replaceAll(modelId,newModel.getId());
                        ((ObjectNode) jsonNode).put (fieldName, text);
                    }
                }


                // 复制抄送用户
                if (node.get("properties") != null && node.get("properties").get("ccusers") != null){
                    String ccUser = node.get("properties").get("ccusers").asText();
                    if (StringUtils.isNotBlank(ccUser)){
                        JsonNode propertiesNode = node.get("properties");
                        ((ObjectNode) propertiesNode).put ("ccusers", wfActApproverService.copyByUuid(ccUser));
                    }
                }

            }
        }
    }


    /**
     * 保存模型
     * @param actModelVo
     * @return
     */
    public AjaxResult saveModel(ActModelVo actModelVo) throws UnsupportedEncodingException {
        if (actModelVo.getCopyModel()){
            return this.copyModel(actModelVo);
        }else {
            return this.save(actModelVo);
        }
    }



    /**
     * 保存模型
     *
     * @param actModelVo
     * @return
     */
    public AjaxResult save(ActModelVo actModelVo) throws UnsupportedEncodingException {
        Model model = null;

        if (StringUtils.isNotBlank(actModelVo.getId())) {
            model = repositoryService.getModel(actModelVo.getId());
        } else {
            model = repositoryService.newModel();
        }

        model.setKey(actModelVo.getKey());
        model.setName(actModelVo.getName());
        model.setCategory(actModelVo.getCategory());
        model.setVersion(Integer.parseInt(String.valueOf(repositoryService.createModelQuery().modelKey(model.getKey()).count() + 1)));

        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode modelObjectNode = objectMapper.createObjectNode();
        modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, model.getName());
        modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, model.getVersion());
        modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, "1");
        modelObjectNode.put("formType", actModelVo.getFormType());
        modelObjectNode.put("formId", actModelVo.getFormId());
//        modelObjectNode.put("procInstDraftUrl",procInstDraftUrl);
//        modelObjectNode.put("procInstViewUrl",procInstViewUrl);
//        modelObjectNode.put("procInstStartRePerm",procInstStartRequiredPermissionId);
        model.setMetaInfo(modelObjectNode.toString());


        repositoryService.saveModel(model);

        if (StringUtils.isBlank(actModelVo.getId())) {
            ObjectNode editorNode = objectMapper.createObjectNode();
            editorNode.put("id", "canvas");
            editorNode.put("resourceId", "canvas");
            ObjectNode properties = objectMapper.createObjectNode();
            properties.put("process_id", model.getKey());
            properties.put("process_author", "lms");
            properties.put("name", model.getName());
            properties.put("documentation", model.getCategory());
            editorNode.set("properties", properties);
            ObjectNode stencilset = objectMapper.createObjectNode();
            stencilset.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
            editorNode.set("stencilset", stencilset);
            repositoryService.addModelEditorSource(model.getId(), editorNode.toString().getBytes("utf-8"));
        }


        return AjaxResult.success();

    }

    /**
     * 删除模型
     *
     * @param id 模型ID
     * @return
     */
    public AjaxResult delete(String id) {
        repositoryService.deleteModel(id);
        return AjaxResult.success();
    }

    /**
     * 部署流程
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Transactional(readOnly = false)
    public void deploy(String id) throws Exception {

        // 获取模型
        Model model = repositoryService.getModel(id);

        ObjectNode objectNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(model.getId()));
        BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(objectNode);

        String processName = model.getName();
        if (!org.apache.commons.lang3.StringUtils.endsWith(processName, ".bpmn20.xml")) {
            processName += ".bpmn20.xml";
        }

        try {
            // 部署流程 流程部署的分类存的是流程模型的ID
            Deployment deployment = repositoryService.createDeployment().name(model.getName())
                    .addBpmnModel(processName, bpmnModel).category(model.getId())
                    .deploy();

            // 设置流程分类
            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();

            for (ProcessDefinition processDefinition : list) {
                repositoryService.setProcessDefinitionCategory(processDefinition.getId(), model.getCategory());
            }

        } catch (Exception e) {
            logger.error("部署流程异常", e);
        }
    }

    /**
     * 校验流程标识是否重复
     *
     * @param actModelVo
     * @return
     */
    public boolean checkKey(ActModelVo actModelVo) {
        Model model = repositoryService.createModelQuery().modelKey(actModelVo.getKey()).latestVersion().singleResult();
        if (model == null) {
            return true;
        }
        if (StringUtils.isNotBlank(actModelVo.getId()) && (actModelVo.getId().equals(model.getId()) && !actModelVo.getCopyModel() )) {
            return true;
        }
        return false;
    }

    /**
     * 模型导入
     * @param file 导入文件
     * @return
     */
    public void importData(MultipartFile file){
        Map<String,String> modelMap = new HashMap<String, String>();
        Map<String,String> dataMap = new HashMap<String, String>();
        InputStream fileInputStream = null;
        Deployment deployment = null;

        try {
            fileInputStream = file.getInputStream();
            ZipInputStream zip = new ZipInputStream(fileInputStream);
            ZipEntry entry = zip.getNextEntry();
            while (entry != null){
                String entryName =entry.getName();
                if (entryName.endsWith(BPMN)) {
                    String modelName=entryName.substring(0,entryName.indexOf(BPMN));
                    deployment = repositoryService.createDeployment().addInputStream(entryName, zip).deploy();
                    modelMap.put(deployment.getId(), modelName);
                } else{
                    byte[] bytes = IoUtil.readInputStream(zip, entry.getName());
                    String text=new String(bytes, StandardCharsets.UTF_8);
                    dataMap.put(entry.getName(),text);
                }
                entry = zip.getNextEntry();
            }

            Set<String> Set = modelMap.keySet();
            for (String deploymentKey : Set) {
                String modelName=modelMap.get(deploymentKey);
                // 导入流程分类
                this.importCategory(deploymentKey, dataMap.get(modelName + CATEGORY));
                // 导入流程表单
                this.importForm( dataMap.get(modelName + FORM));
                // 导入审批人
                this.importApproval(dataMap.get(modelName + APPROVAL));
            }

        }catch (Exception e){
            LogUtils.error("流程导入异常",e);
        }finally {
            if (fileInputStream != null){
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    LogUtils.error(e.getMessage(),e);
                }
            }
        }




    }

    /**
     * 导入流程分类
     * @param text 文件
     */
    public void importCategory(String deploymentKey,String text){
        JSONObject categoryJson = JSONObject.parseObject(text);
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentKey).list();
        for (ProcessDefinition processDefinition : list) {
            //repositoryService.setProcessDefinitionCategory(processDefinition.getId(),categoryJson.getString("category"));

            try {
                // 将流程转化为模型
                this.convertToModel(processDefinition.getId(),categoryJson.getJSONObject("metaInfo"));
            } catch (Exception e) {
                LogUtils.error("流程转化为模型异常",e);
            }


        }

    }

    /**
     * 导入流程表单
     * @param text 文件
     */
    public void importForm(String text){

    }

    /**
     * 导入审批人
     * @param text 文件
     */
    public void importApproval(String text){
        JSONArray approvalAllArray = JSONArray.parseArray(text);
        Map<String,JSONArray> approvalMap = new HashMap<>();

        for (int i = 0; i < approvalAllArray.size(); i++) {
            JSONObject approvalJson = approvalAllArray.getJSONObject(i);
            String actUuid = approvalJson.getString("actUuid");
            JSONArray approvalArray = approvalMap.get(actUuid);
            if (approvalArray == null){
                approvalArray = new JSONArray();
            }
            approvalArray.add(approvalJson);
            approvalMap.put(actUuid,approvalArray);
        }

        Set<String> keySet = approvalMap.keySet();
        for (String key : keySet) {
            wfActApproverDao.deleteByActUuid(key);
            JSONArray jsonArray = approvalMap.get(key);
            for (int i = 0; i < jsonArray.size(); i++) {
                wfActApproverService.save(new WfActApprover(jsonArray.getJSONObject(i)));
            }
        }

    }

    /**
     * 模型导出
     * @param actModelExportDTO 导出模型
     * @return
     */
    public void export(ActModelExportDTO actModelExportDTO, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String zpiName = UUID.randomUUID().toString() + ".zip";
        // 服务器临时文件地址
        String outFilePath = RuoYiConfig.getProfile() + File.separator + "temp" + File.separator + "actModelExport";
        File file = new File(outFilePath + File.separator + zpiName);
        // 文件输出流
        FileOutputStream outStream = null;
        // 压缩流
        ZipOutputStream toClient = null;

        try {
            AttUtils.createFile(outFilePath, zpiName);
            outStream = new FileOutputStream(file);
        } catch (Exception e) {
            logger.error("创建文件流异常",e);
        }

        try {
            // 压缩流
            toClient = new ZipOutputStream(outStream);
            for (int i = 0; i < actModelExportDTO.getModelIds().size(); i++) {
                String modelId = actModelExportDTO.getModelIds().getString(i);
                Model model = repositoryService.createModelQuery().modelId(modelId).singleResult();
                BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
                byte[] modelEditorSource = repositoryService.getModelEditorSource(model.getId());
                if (modelEditorSource != null) {
                    JsonNode editorNode = new ObjectMapper().readTree(modelEditorSource);
                    BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);

                    // 流程图XML
                    LogUtils.info("导出流程图XML");
                    this.exportXml(bpmnModel, toClient);

                    // 获取节点审批人配置
                    LogUtils.info("导出节点审批人配置");
                    this.exportApproval(model, toClient, editorNode, bpmnModel);

                    // 流程分类信息等
                    LogUtils.info("流程分类信息等");
                    this.exportCategory(model, toClient, bpmnModel);

                    // 导出表单信息
                    LogUtils.info("导出表单信息");
                    this.exportForm(model, toClient, bpmnModel);

                }

            }

        } catch (Exception e) {
            LogUtils.error("流程导出异常",e);
        } finally {
            if (toClient != null){
                toClient.finish();
                toClient.close();
            }
            if (outStream != null){
                outStream.flush();
                outStream.close();
            }

        }
        FileUtils.download(file,request,response);


    }

    /**
     * 导出表单信息
     * @param model
     */
    public void exportForm(Model model,ZipOutputStream toClient,BpmnModel bpmnModel){
        JSONObject metaInfo = JSONObject.parseObject(model.getMetaInfo());
        String formType = metaInfo.getString("formType");
        String formId = metaInfo.getString("formId");
        if ("dev".equals(formType)){
            WfApplyForm wfApplyForm = wfApplyFormService.getById(formId);
            ByteArrayInputStream inputStream = null;
            try {
                inputStream = new ByteArrayInputStream(wfApplyForm.toJson().getBytes());
                AttUtils.zipFile(inputStream, toClient,bpmnModel.getMainProcess().getId()+".form.txt");
            }catch (Exception e){
                LogUtils.error("导出流程表单异常",e);
            }finally {
                if (inputStream != null){
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        LogUtils.error("关闭inputStream异常",e);
                    }
                }
            }

        }

    }


    /**
     * 流程图XML
     * @param bpmnModel 模型对象
     * @param toClient 压缩流
     */
    public void exportXml(BpmnModel bpmnModel,ZipOutputStream toClient){
        BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
        byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
        String filename = bpmnModel.getMainProcess().getId() + ".bpmn20.xml";
        ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
        AttUtils.zipFile(in, toClient,filename);
    }

    /**
     * 导出流程分类等
     * @param model 模型对象
     * @param toClient 压缩流
     */
    public void exportCategory(Model model,ZipOutputStream toClient,BpmnModel bpmnModel){
        JSONObject category = new JSONObject();
        category.put("category", model.getCategory());
        JSONObject metaInfo = JSONObject.parseObject(model.getMetaInfo());
        category.put("metaInfo",metaInfo);
        ByteArrayInputStream categoryInputStream = new ByteArrayInputStream(category.toJSONString().getBytes());
        AttUtils.zipFile(categoryInputStream, toClient,bpmnModel.getMainProcess().getId()+".category.txt");
    }

    /**
     * 根据模型ID导出
     * @param model 模型
     */
    public void exportApproval(Model model, ZipOutputStream toClient, JsonNode editorNode, BpmnModel bpmnModel) {
        //获取审批人的数据
        JSONArray JsonArray = this.getApprovalJsonArray(model, editorNode);
        ByteArrayInputStream InputStream = new ByteArrayInputStream(JsonArray.toJSONString().getBytes());
        AttUtils.zipFile(InputStream, toClient, bpmnModel.getMainProcess().getId() + ".wf_act_approval.txt");

    }

    /**
     * 根据流程节点，获取节点审批人配置的UUID
     * @param model 模型对象
     * @param editorNode
     * @return
     */
    public JSONArray getApprovalJsonArray(Model model,JsonNode editorNode){
        JSONArray resJson = new JSONArray();
        List<WfActApprover> wfApprovalList = this.getActUuid(editorNode, model.getId());
        for (WfActApprover wfActApprover : wfApprovalList) {
            resJson.add(wfActApprover.toJson());
        }
        return resJson;
    }

    /**
     * 根据流程节点，获取节点审批人配置的UUID
     * @param jsonNode
     * @param modelId
     * @return
     */
    public List<WfActApprover> getActUuid(JsonNode jsonNode,String modelId){
        List<WfActApprover> list=new ArrayList<WfActApprover>();
        JsonNode childShapes = jsonNode.get("childShapes");
        if (childShapes!=null) {
            for (JsonNode childShape : childShapes) {

                if (childShape.get("properties")!=null && childShape.get("properties").get("usertaskassignment")!=null
                        && childShape.get("properties").get("usertaskassignment").get("assignment")!=null
                        && childShape.get("properties").get("usertaskassignment").get("assignment").get("candidateUsers")!=null) {

                    JsonNode candidateUsers = childShape.get("properties").get("usertaskassignment").get("assignment").get("candidateUsers");

                    for (JsonNode candidateUser : candidateUsers) {
                        String approverListener  = candidateUser.get("value").textValue();
                        if (approverListener.contains("${approverListener.getApproverString(execution")) {
                            String actUuid= approverListener.split("'")[1];
                            List<WfActApprover> ActApprovals = wfActApproverService.findList(actUuid);
                            list.addAll(ActApprovals);
                        }
                    }
                }

                // 抄送用户
                if (childShape.get("properties")!=null && childShape.get("properties").get("ccusers")!=null && !"".equals(childShape.get("properties").get("ccusers").toString().replace("\"",""))){
                    String ccUsers = childShape.get("properties").get("ccusers").toString().replace("\"","");
                    if (StringUtils.isNotBlank(ccUsers)){
                        List<WfActApprover> ActApprovals = wfActApproverService.findList(ccUsers);
                        list.addAll(ActApprovals);
                    }
                }


                //
                if (childShape.get("properties")!=null && childShape.get("properties").get("multiinstance_collection") !=null) {
                    String multiinstanceCollection = childShape.get("properties").get("multiinstance_collection").textValue();
                    if (multiinstanceCollection.contains("${approverListener.getApproverList(execution")) {
                        String actUuid= multiinstanceCollection.split("'")[1];
                        List<WfActApprover> ActApprovals = wfActApproverService.findList(actUuid);
                        list.addAll(ActApprovals);
                    }

                }

            }
        }
        return list;
    }


    /**
     * 将部署的流程转换为模型
     * @param procDefId
     * @throws UnsupportedEncodingException
     * @throws XMLStreamException
     */
    @Transactional(readOnly = false)
    public org.activiti.engine.repository.Model convertToModel(String procDefId,JSONObject metaInfo) throws IOException, XMLStreamException {

        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId).singleResult();
        InputStream bpmnStream = null;
        try {
            bpmnStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
        }finally {
            bpmnStream.close();
        }
        XMLInputFactory xif = XMLInputFactory.newInstance();
        xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
        xif.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
        InputStreamReader in = new InputStreamReader(bpmnStream, StandardCharsets.UTF_8);
        XMLStreamReader xtr = xif.createXMLStreamReader(in);

        BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);

        BpmnJsonConverter converter = new BpmnJsonConverter();
        ObjectNode modelNode = converter.convertToJson(bpmnModel);
        org.activiti.engine.repository.Model modelData = repositoryService.newModel();
        modelData.setKey(processDefinition.getKey());
        modelData.setName(processDefinition.getName());
        modelData.setCategory(processDefinition.getDescription());//.getDeploymentId());
        modelData.setDeploymentId(processDefinition.getDeploymentId());
        Model lastVersionModel = repositoryService.createModelQuery().modelKey(modelData.getKey()).latestVersion().singleResult();

        int lastVersion = lastVersionModel != null ? lastVersionModel.getVersion()+1 : 1;
        modelData.setVersion(lastVersion);

        ObjectNode modelObjectNode = new ObjectMapper().createObjectNode();
        modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName());
        modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, modelData.getVersion());
        modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription());

        if (metaInfo!=null) {
            if (metaInfo.getString("formId")!=null) {
                modelObjectNode.put("formId",metaInfo.getString("formId"));
            }
            if (metaInfo.getString("formType")!=null) {
                modelObjectNode.put("formType",metaInfo.getString("formType"));
            }

        }


        modelData.setMetaInfo(modelObjectNode.toString());

        repositoryService.saveModel(modelData);

        repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes("utf-8"));

        return modelData;
    }

}
